<!DOCTYPE html>
<title>MediaCapabilities.decodingInfo() for encrypted media</title>
<meta name="timeout" content="long">
<script src=/resources/testharness.js></script>
<script src="/resources/testharnessreport.js"></script>
<script>

// Minimal VideoConfiguration that will be allowed per spec. All optional
// properties are missing.
var minimalVideoConfiguration = {
  contentType: 'video/webm; codecs="vp09.00.10.08"',
  width: 800,
  height: 600,
  bitrate: 3000,
  framerate: 24,
};

// Minimal AudioConfiguration that will be allowed per spec. All optional
// properties are missing.
var minimalAudioConfiguration = {
  contentType: 'audio/webm; codecs="opus"',
};

// Minimal MediaCapabilitiesKeySystemConfiguration that will be allowed per
// spec. All optional properties are missing.
var minimalKeySystemConfiguration = {
  keySystem: 'org.w3.clearkey',
};

// Config with bogus name not provided by any UA.
var bogusKeySystemConfiguration = {
  keySystem: 'bogus',
};

promise_test(t => {
  return navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    video: minimalVideoConfiguration,
    keySystemConfiguration: minimalKeySystemConfiguration,
  });
}, "Test that decodingInfo() accepts a stub key system configuration (w/video).");

promise_test(t => {
  return navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    audio: minimalAudioConfiguration,
    keySystemConfiguration: minimalKeySystemConfiguration,
  });
}, "Test that decodingInfo() accepts a stub key system configuration (w/audio).");

promise_test(t => {
  return navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    video: minimalVideoConfiguration,
    keySystemConfiguration: {
      keySystem: 'org.w3.clearkey',
      video: {
        robustness: '',
      },
    },
  });
}, "Test that decodingInfo() accepts a key system configuration with video info.");

promise_test(t => {
  return navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    audio: minimalAudioConfiguration,
    keySystemConfiguration: {
      keySystem: 'org.w3.clearkey',
      audio : {
        robustness: '',
      },
    },
  });
}, "Test that decodingInfo() accepts a key system configuration with audio info.");

promise_test(t => {
  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    audio: minimalAudioConfiguration,
    keySystemConfiguration: {
      keySystem: 'org.w3.clearkey',
      video: {
        robustness: '',
      },
    },
  }));
}, "Test that decodingInfo() rejects if robustness and configuration do not match (1).");

promise_test(t => {
  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    video: minimalVideoConfiguration,
    keySystemConfiguration: {
      keySystem: 'org.w3.clearkey',
      audio : {
        robustness: '',
      },
    },
  }));
}, "Test that decodingInfo() rejects if robustness and configuration do not match (2).");

promise_test(t => {
  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    video: minimalVideoConfiguration,
    keySystemConfiguration: {
      keySystem: 'org.w3.clearkey',
      audio : {
        robustness: '',
      },
      video: {
        robustness: '',
      },
    },
  }));
}, "Test that decodingInfo() rejects if robustness and configuration do not match (3).");

promise_test(t => {
  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    audio: minimalAudioConfiguration,
    video: minimalVideoConfiguration,
    keySystemConfiguration: {
      keySystem: 'org.w3.clearkey',
      audio : {
        robustness: '',
      },
      video: {
        robustness: '',
      },
      persistentState: "foobar",
    },
  }));
}, "Test that decodingInfo() rejects if persistentState isn't valid.");

promise_test(t => {
  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    audio: minimalAudioConfiguration,
    video: minimalVideoConfiguration,
    keySystemConfiguration: {
      keySystem: 'org.w3.clearkey',
      audio : {
        robustness: '',
      },
      video: {
        robustness: '',
      },
      distinctiveIdentifier: "foobar",
    },
  }));
}, "Test that decodingInfo() rejects if distinctiveIdentifier isn't valid.");

promise_test(t => {
  return promise_rejects_js(t, TypeError, navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    audio: minimalAudioConfiguration,
    video: minimalVideoConfiguration,
    keySystemConfiguration: {
      keySystem: 'org.w3.clearkey',
      audio : {
        robustness: '',
      },
      video: {
        robustness: '',
      },
      sessionTypes: "foobar",
    },
  }));
}, "Test that decodingInfo() rejects if sessionTypes isn't a sequence.");

promise_test(t => {
  return navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    audio: minimalAudioConfiguration,
    video: minimalVideoConfiguration,
    keySystemConfiguration: {
      keySystem: {},
      initDataType: {},
      audio : {
        robustness: '',
      },
      video: {
        robustness: '',
      },
    },
  });
}, "Test that decodingInfo() does not reject when properties are set to unexpected values.");

promise_test(t => {
  return navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    video: minimalVideoConfiguration,
    audio: minimalAudioConfiguration,
    keySystemConfiguration: minimalKeySystemConfiguration,
  }).then(ability => {
    assert_equals(typeof ability.supported, "boolean");
    assert_equals(typeof ability.smooth, "boolean");
    assert_equals(typeof ability.powerEfficient, "boolean");
    assert_equals(typeof ability.keySystemAccess, "object");
  });
}, "Test that decodingInfo returns a valid MediaCapabilitiesDecodingInfo objects with encrypted media");

promise_test(t => {
  return navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    video: minimalVideoConfiguration,
    keySystemConfiguration: {
      keySystem: 'foobar',
      video: {
        robustness: '',
      },
    }
  }).then(ability => {
    assert_false(ability.supported);
    assert_false(ability.smooth);
    assert_false(ability.powerEfficient);
    assert_equals(ability.keySystemAccess, null);
  });
}, "Test that random key systems are reported as non supported.");

// TODO(mlamouri): this test could be split in two tests for which codec support
// across browsers is widely compatible: one when all browsers wouldn't support
// and one where all browsers do support. The current approach is to check that
// the answer is consistent to the spec.
promise_test(t => {
  return navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    video: minimalVideoConfiguration,
    audio: minimalAudioConfiguration,
    keySystemConfiguration: minimalKeySystemConfiguration,
  }).then(ability => {
    if (ability.supported)
      assert_not_equals(ability.keySystemAccess, null);
    else
      assert_equals(ability.keySystemAccess, null);
  });
}, "Test that keySystemAccess is only null when not supported if keySystemConfiguration was used.");

promise_test(t => {
  return navigator.mediaCapabilities.decodingInfo({
    type: 'file',
    video: minimalVideoConfiguration,
    audio: minimalAudioConfiguration,
    // Supply bogus config to reliably result in a null keySystemAccess.
    keySystemConfiguration: bogusKeySystemConfiguration,
  }).then(ability => {
    assert_equals(ability.keySystemAccess, null);
    assert_false(ability.supported);
  });
}, "Test that supported=false when keySystemConfiguration is unsupported.");
</script>
